const OSS = require('ali-oss');
const fs = require('fs');

class OSSClient {
	constructor(region, accessKeyId, accessKeySecret, bucket) {
		this.client = new OSS({
			region: region,
			accessKeyId: accessKeyId,
			accessKeySecret: accessKeySecret,
			bucket: bucket
		});
	}
	//单文件上传
	put(path, buf) {
		let self = this;
		return new Promise(function (resolve, reject) {
			self.client.put(path, buf).then(function (r) {
				resolve(r);
			}).catch(err => {
				reject(err);
			});
		});
	}
	//文件夹上传
	async putFolder(path, localPath) {
		const files = fs.readdirSync(localPath);
		if (files.length) {
			if (path.charAt(path.length - 1) != "/") {
				path += "/";
			}
			if (localPath.charAt(localPath.length - 1) != "/") {
				localPath += "/";
			}
			let folder = this.cutFinalPath(localPath);
			for (let i = 0; i < files.length; i++) {
				if (files[i].charAt(0)!="." && files[i].charAt(0)!="~") {
					let filepath = localPath+files[i];
					let filestat = fs.statSync(filepath);
					if (filestat.isFile()) {
						let file = fs.readFileSync(filepath);
						await this.put(path+folder+files[i], file);
					} else if(filestat.isDirectory()) {
						await this.putFolder(path+folder, filepath);
					}
				}
			}
		}
	}
	//单文件下载
	get(path) {
		let self = this;
		return new Promise(function (resolve, reject) {
			self.client.get(path).then(function (r) {
				resolve(r);
			}).catch(err => {
				reject(err);
			});
		});
	}
	//目录文件列表
	async listDir(path, max = 10000) {
		if (path.charAt(path.length - 1) != "/") {
			path += "/";
		}
		if (max > 500) {
			max = parseInt(max / 500) + 1;
		} else {
			max = 1;
		}
		let ret = { objects: [], prefixes: [] };
		let marker = null;
		try {
			for (let i = 0; i < max; i++) {
				let list = await this.client.list({ prefix: path, delimiter: '/', "max-keys": 500, marker: marker });
				if (list.objects && list.objects.length > 0) {
					ret.objects.push(...list.objects);
				}
				if (list.prefixes && list.prefixes.length > 0) {
					ret.prefixes.push(...list.prefixes);
				}
				if (list.isTruncated && list.nextMarker) {
					marker = list.nextMarker;
				} else {
					break;
				}
			}
		} catch (error) {
			console.error(error);
		}
		return ret;
	}
	//多文件删除
	del(path, all, ...files) {
		let self = this;
		if (path.charAt(path.length - 1) != "/") {
			path += "/";
		}
		for (let i = 0; i < files.length; i++) {
			files[i] = path + files[i];
		}
		if (all) {
			files.push(path);
		}
		return new Promise(function (resolve, reject) {
			self.client.deleteMulti(files).then(function (r) {
				if (r.res.statusCode == 200) {
					resolve(r);
				} else {
					reject(r);
				}
			}).catch(function (err) {
				reject(err);
			});
		})
	}
	//递归删除目录
	async delPath(path, max = 10000) {
		if (path.charAt(path.length - 1) != "/") {
			path += "/";
		}
		let list = await this.listDir(path, max);
		// console.log(list.prefixes);
		if (list.prefixes.length > 0) {
			for (let i = 0; i < list.prefixes.length; i++) {
				let ret = await this.delPath(list.prefixes[i]);
			}
		}
		if (list.objects.length > 0) {
			for (let j = 0; j < list.objects.length; j++) {
				// console.log(list.objects[j].name);
				let ret = await this.client.delete(list.objects[j].name);
			}
		}
	}
	//单文件拷贝，同一个Bucket内的文件
	copy(from, to) {
		let self = this;
		return new Promise(function (resolve, reject) {
			self.client.copy(to, from).then((res) => {
				resolve(res);
			}).catch(err => {
				reject(err);
			})
		});
	}
	//拷贝目录下的所有文件，同一个Bucket内的文件
	async copyPath(from, to, max = 10000) {
		if (from.charAt(from.length - 1) != "/") {
			from += "/";
		}
		if (to.charAt(to.length - 1) != "/") {
			to += "/";
		}
		try {
			let list = await this.listDir(from, max);
			if (list.objects.length > 0) {
				for (let j = 0; j < list.objects.length; j++) {
					if (list.objects[j].name.charAt(list.objects[j].name.length - 1) == "/") {
						continue;
					}
					let cp = await this.client.copy(to + this.cutFilename(list.objects[j].name), list.objects[j].name);
				}
			}
			if (list.prefixes.length > 0) {
				for (let j = 0; j < list.prefixes.length; j++) {
					let cpp = await this.copyPath(list.prefixes[j], to + this.cutFinalPath(list.prefixes[j]), max);
				}
			}
		} catch (error) {
			console.error(error);
		}
	}
	//判断文件是否存在
	async isExistObject(name, options = {}) {
		try {
			await this.client.head(name, options);
			return true;
		 }  catch (error) {
			// if (error.code === 'NoSuchKey') {
			// 	return false;
			// }
			return false;
		 }
	}
	//取文件名
	cutFilename(path) {
		if (path.length > 3) {
			let index = path.lastIndexOf('/');
			if (index >= 0) {
				return path.substring(index + 1, path.length);
			}
		}
		return path;
	}
	//取最后一个目录
	cutFinalPath(path) {
		if (path.length > 2) {
			let index = path.lastIndexOf('/', path.length - 2);
			if (index >= 0) {
				return path.substring(index + 1, path.length);
			}
		}
		return path;
	}
}

module.exports = OSSClient;
